package com.supermarket.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.supermarket.annotation.OperationLogAnnotation;
import com.supermarket.dto.CategoryPageQueryDto;
import com.supermarket.entity.Category;
import com.supermarket.service.CategoryService;
import com.supermarket.utils.PageResult;
import com.supermarket.utils.Result;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Api(tags = "分类管理")
@RestController
@RequestMapping("/category")
@Slf4j
@RequiredArgsConstructor
public class CategoryController {

    private final CategoryService categoryService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 分页查询分类列表
     */
    @GetMapping("/list")
    @Operation(summary = "分页查询分类列表")
    public Result<PageResult> list(CategoryPageQueryDto categoryPageQueryDto) {
        log.info("分页查询分类列表：{}", categoryPageQueryDto);
        PageResult pageResult = categoryService.list(categoryPageQueryDto);
        return Result.success(pageResult);
    }



    // Jackson ObjectMapper 实例化
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 根据id查询分类，使用Redis缓存
     */
    @GetMapping("/{id}")
    @Operation(summary = "根据id查询分类")
    public Result<Category> getById(@PathVariable Long id) {
        log.info("根据id查询分类：{}", id);

        // 先从缓存中查询
        String cacheKey = "category:" + id;
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        String categoryJson = valueOperations.get(cacheKey);
        Category category = null;

        if (categoryJson != null) {
            // 如果缓存中有数据，直接返回缓存数据
            try {
                category = objectMapper.readValue(categoryJson, Category.class); // 反序列化 JSON 为对象
                log.info("从缓存中获取分类：{}", category);
            } catch (Exception e) {
                log.error("反序列化缓存数据失败", e);
            }
        } else {
            // 如果缓存没有数据，从数据库查询并存入缓存
            category = categoryService.getById(id);
            if (category != null) {
                try {
                    String categoryJsonToCache = objectMapper.writeValueAsString(category);  // 序列化对象为 JSON 字符串
                    valueOperations.set(cacheKey, categoryJsonToCache);  // 存入 Redis
                    log.info("从数据库中获取分类并存入缓存：{}", category);
                } catch (Exception e) {
                    log.error("序列化分类数据失败", e);
                }
            }
        }
        return Result.success(category);
    }

    /**
     * 新增分类，清除缓存
     */
    @PostMapping
    @Operation(summary = "新增分类")
    @OperationLogAnnotation(operation = "新增分类", operationType = "新增")
    public Result<String> save(@RequestBody Category category) {
        log.info("新增分类：{}", category);
        categoryService.save(category);

        // 清除分类缓存
        stringRedisTemplate.delete("category:" + category.getId());

        return Result.success();
    }


    /**
     * 更新分类，更新缓存
     */
    @PutMapping
    @Operation(summary = "更新分类")
    @OperationLogAnnotation(operation = "更新分类信息", operationType = "更新")
    public Result<String> update(@RequestBody Category category) {
        log.info("更新分类：{}", category);

        // 更新数据库中的分类
        categoryService.update(category);

        // 更新缓存
        String cacheKey = "category:" + category.getId();
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();

        try {
            // 将 Category 对象序列化为 JSON 字符串
            String categoryJson = objectMapper.writeValueAsString(category);

            // 将更新后的分类数据存入 Redis
            valueOperations.set(cacheKey, categoryJson);
            log.info("更新分类并将其存入缓存：{}", category);
        } catch (Exception e) {
            log.error("序列化分类数据失败并存入缓存", e);
        }

        return Result.success();
    }

    /**
     * 删除分类，清除缓存
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除分类")
    @OperationLogAnnotation(operation = "删除分类", operationType = "删除")
    public Result<String> delete(@PathVariable Long id) {
        log.info("删除分类：{}", id);
        categoryService.delete(id);

        // 清除缓存
        stringRedisTemplate.delete("category:" + id);

        return Result.success();
    }

    /**
     * 启用/禁用分类，清除缓存
     */
    @PutMapping("/status/{status}/{id}")
    @Operation(summary = "启用/禁用分类")
    @OperationLogAnnotation(operation = "修改分类状态", operationType = "更新")
    public Result<String> enableOrDisable(
            @Parameter(description = "状态，1为启用，0为禁用") @PathVariable Integer status,
            @Parameter(description = "分类ID") @PathVariable Long id) {
        log.info("启用/禁用分类：status={}, id={}", status, id);
        categoryService.enableOrDisable(status, id);

        // 清除缓存
        stringRedisTemplate.delete("category:" + id);

        return Result.success();
    }

    /**
     * 获取所有分类列表（用于下拉框）
     */
    @GetMapping("/listAll")
    @Operation(summary = "获取所有分类列表")
    public Result<List<Category>> listAll() {
        log.info("获取所有分类列表");
        List<Category> categories = categoryService.listAll();
        return Result.success(categories);
    }
}
